import { Vec3, color } from 'cc';
import { deepclone } from './../../../../../scripts/libs/utils/deepclone/deepclone';
import { PipeView } from './PipeView';
import { _decorator, Node } from 'cc';
import { BaseView } from '../../../../../scripts/libs/rxjs/cc3/BaseView';
import { v2 } from 'cc';
import { CellType, StageInfo } from '../../../game/basic';
import { v3 } from 'cc';
import { ResourceHelper } from '../../../ResourceHelper';
import { PillarView } from './PillarView';
import { BindNodeTouchWithClick } from '../../../../../scripts/libs/rxjs/cc3/BindNode';
import { lm } from '../../../LobbyManager';
import { EventTouch } from 'cc';
import { UITransform } from 'cc';
import { Subscription, count } from 'rxjs';
import { Timer } from '../../../../../scripts/libs/rxjs/cc3/CreatorSchedule';
import { gm } from '../../../../../scripts/managers/GameManager';
import { nullifySubscription } from '../../../../../scripts/libs/rxjs/utils';
// import { GameWinPanel } from '../../GameWinPanel/GameWinPanel';
import { GamePanel } from '../GamePanel';
import { FlowStatus } from '../../../Enums';
import { EditorGameWinPanel } from '../../EditorGamePanel/EditorGameWinPanel';
import { EditorGameLosePanel } from '../../EditorGamePanel/EditorGameLosePanel';
import { MergeASAP } from '../../../../../scripts/libs/rxjs/cc3/Merge';
import { udm } from '../../../../../scripts/managers/UserDataManager';
import { DevConfig } from '../../../../../scripts/managers/DevConfig';
import { timem } from '../../../../../scripts/managers/TimeManager';
import { GameWinPanel } from '../../GameWinPanel/GameWinPanel';
import { GameLosePanel } from '../../GameLosePanel/GameLosePanel';
import { view } from 'cc';
import { MeshRenderer } from 'cc';
const { ccclass, property } = _decorator;
const _v30 = v3();

@ccclass('StageView')
export class StageView extends BaseView {

    gamePanel: GamePanel = null;

    stageInfo: StageInfo = null;

    @property(Node)
    gridContainer: Node = null;

    @property(Node)
    groundContainer: Node = null;

    @property(Node)
    ropeContainer: Node = null;

    @property(Node)
    commonContainer: Node = null;

    @property(Node)
    frontContainer: Node = null;

    willBind(): void {
        globalThis.stage2d = this;
        gm.stageView = this;
        gm.pauseReason.add('load');
    }

    useObserves() {
        return [
            BindNodeTouchWithClick(this.node, lm.uiRoot.camera).subscribe(this.handleTouch.bind(this)),

            gm.isWin.subscribe(_ => _ ? gm.pauseReason.add('win') : gm.pauseReason.delete('win')),
            gm.isLose.subscribe(_ => _ ? gm.pauseReason.add('lose') : gm.pauseReason.delete('lose')),

            gm.forceWinCommand.subscribe(_ => this.determineWin()),
            gm.forceLoseCommand.subscribe(_ => this.determineLose()),

            MergeASAP(gm.isWin, gm.isLose).subscribe(_ => {
                if (gm.isWin.value || gm.isLose.value) {
                    nullifySubscription.call(this, '_sub_delay_check');
                    // this.timeStopCount();
                }
            }),
        ];
    }

    afterClose() {
        this.stageSubscriptions.forEach(_ => _ && _.unsubscribe());
        this.stageSubscriptions.splice(0, this.stageSubscriptions.length);
        this.recycleGround();
    }

    onDestroyView(): void {
        nullifySubscription.call(this, '_delay_in_win_panel');
        nullifySubscription.call(this, '_delay_in_lose_panel');
        nullifySubscription.call(this, '_sub_delay_check');
        nullifySubscription.call(this, '_sub_time');
        nullifySubscription.call(this, '_sub_lose_gray_anim');
        gm.isWin.value = false;
        gm.isLose.value = false;
    }

    Space = v2(160, 160);

    rowWidthGrowthRate = 0;

    get Width(): number {
        return this.stageInfo?.width ?? 0;
    }

    get Height(): number {
        return this.stageInfo?.height ?? 0;
    }

    getIdxByRowCol(rc: number[]) {
        return rc[0] * this.Width + rc[1];
    }
    getRowColPos(idx: number): number[] {
        return [Math.floor(idx / this.Width), idx % this.Width]; // 得到行列坐标，上到下，左到右
    }
    getPositionByIdx(idx: number, isWorld = false) {
        let [row, col] = this.getRowColPos(idx);
        return this.getPositionByRowCol(row, col, isWorld);
    }
    getPositionByRowCol(row: number, col: number, isWorld = false) {
        // let x = col * this.Space.x - this.Space.x * this.Width / 2 + this.Space.x / 2;
        // let y = row * -this.Space.y + this.Space.y * this.Height / 2 - this.Space.y / 2;
        // return v3(x, y, 0);

        // 动态计算当前行格子宽度（Y减小则宽度增大）
        const currentRowWidth = this.Space.x * (1 + this.rowWidthGrowthRate * (row));

        // 计算该行总宽度并居中
        const totalRowWidth = currentRowWidth * this.Width;
        const x = col * currentRowWidth - totalRowWidth / 2 + currentRowWidth / 2;

        // Y坐标逻辑保持不变
        const y = row * -this.Space.y + this.Space.y * this.Height / 2 - this.Space.y / 2 - 10;

        if (isWorld) {
            return this.gridContainer.getComponent(UITransform).convertToWorldSpaceAR(v3(x, y, 0));
        }

        return v3(x, y, 0);
    }

    getRowColByPos(position: Vec3) {
        // let x = Math.floor((position.x + this.Space.x * this.Width / 2) / this.Space.x);
        // let y = this.Height - Math.floor((position.y + this.Space.y * this.Height / 2) / this.Space.y) - 1;
        // return [y, x];
        // 根据Y坐标计算行号（逻辑不变）
        const row = this.Height - Math.floor((position.y + this.Space.y * this.Height / 2) / this.Space.y) - 1;

        // 动态获取当前行宽度
        const currentRowWidth = this.Space.x * (1 + this.rowWidthGrowthRate * (row));
        const totalRowWidth = currentRowWidth * this.Width;

        // 根据动态宽度计算列号（严格中心对齐）
        const col = Math.floor((position.x + totalRowWidth / 2) / currentRowWidth);

        return [row, col];
    }
    getIdxByPos(position: Vec3) {
        let [row, col] = this.getRowColByPos(position);
        if (row < 0 || row >= this.Height) return null;
        if (col < 0 || col >= this.Width) return null;
        return this.getIdxByRowCol([row, col]);
    }
    getAdjoin1(posId) {
        let [row, col] = this.getRowColPos(posId);
        let list = [
            { data: [row - 1, col], direction: 1 },
            { data: [row, col + 1], direction: 0 },
            { data: [row, col - 1], direction: 2 },
            { data: [row + 1, col], direction: 3 }
        ];
        return list.filter(_ => {
            let [row, col] = _.data;
            return row >= 0 && row < this.Height && col >= 0 && col < this.Width;
        }).map(_ => {
            let [row, col] = _.data;
            return { idx: this.getIdxByRowCol([row, col]), direction: _.direction };
        });
    }
    getAdjoin1ByDirection(posId: number, direction: number) {
        let candidates = this.getAdjoin1(posId);
        candidates = candidates.filter(_ => _.direction == direction);
        if (candidates.length > 0) {
            return candidates[0]?.idx;
        }
    }

    stageSubscriptions: Subscription[] = [];
    loadStage(stageInfo: StageInfo) {
        this.log('loadStage', stageInfo);
        nullifySubscription.call(this, '_sub_delay_check');
        this.stageSubscriptions.forEach(_ => _ && _.unsubscribe());
        this.stageSubscriptions.splice(0, this.stageSubscriptions.length);
        this.stageInfo = stageInfo;
        // this.grids = stageInfo.grids.map(_ => ({ type: _.type }));
        gm.isWin.value = false;
        gm.isLose.value = false;
        gm.swapperSelected.value = false;
        gm.swapperSelectedIdx.value = null;
        gm.balloonSelected.value = false;
        gm.magnetSelected.value = false;
        gm.continueCount.value = 0;

        gm.itemUseTimes_Swapper.value = 0;
        gm.itemUseTimes_Magnet.value = 0;
        gm.itemUseTimes_Balloon.value = 0;
        gm.coinUse.value = 0;
        gm.reviveTimes.value = 0;
        gm.stageStartAt.value = timem.now();
        gm.curTime.value = 0;
        gm.completed_progress_map.value.clear();

        this.refreshGridsContainer();
        this.genGrids();
        gm.pauseReason.delete('load');
        udm.gameStart(stageInfo);
        udm.gameStartUseHeart();

        // if (stageInfo.stageId >= DevConfig.REQUEST_NOTIFICATION_GREATEREQUAL_STAGE_NUM) {
        //     notification_sdk_m.requestPermission();
        // }
    }

    refreshGridsContainer() {
        let height = this.stageInfo.height * this.Space.y;
        this.gridContainer.getComponent(UITransform).height = height;
        let width = this.stageInfo.width * this.Space.x;
        this.gridContainer.getComponent(UITransform).width = width;

        let viewWidth = view.getVisibleSize().width - 40;
        let targetScale = viewWidth / width;

        this.node.setScale(targetScale, targetScale, targetScale);

    }

    groundMap = new Map<number, Node>();
    recycleGround() {
        for (let [_, groundNode] of this.groundMap) {
            groundNode?.isValid && ResourceHelper.GroundPool.putNode(groundNode);
        }
    }

    genGrids() {
        this.groundContainer.destroyAllChildren();
        this.commonContainer.destroyAllChildren();
        this.ropeContainer.destroyAllChildren();
        for (let i = 0; i < this.stageInfo.height * this.stageInfo.width; i++) {
            let groundNode = ResourceHelper.GroundPool.getNode();
            this.groundMap.set(i, groundNode);
            groundNode.setParent(this.groundContainer);
            groundNode.setPosition(this.getPositionByIdx(i));
        }
        // for (let i = 0; i < this.stageInfo.grids.length; i++) {
        //     let cellInfo = this.stageInfo.grids[i];
        //     if (cellInfo.type == CellType.Pillar) {
        //         this.addPillar(cellInfo);
        //     }
        // }
    }

    handleTouch(param: { type: string, eventTouch: EventTouch, worldPosition: Vec3 }) {
        let { type, worldPosition } = param;
        if (gm.isWin.value || gm.isLose.value) return;

        let position = this.commonContainer.getComponent(UITransform).convertToNodeSpaceAR(worldPosition);
        let idx = this.getIdxByPos(position);
        if (type == 'touch-start') {
            if (idx != null) {
            }
        } else if (type == 'touch-move') {
            if (idx != null) {
            }

        } else if (type == 'touch-end' || type == 'touch-cancel' || type == 'touch-end-click') {
            this.log('handleClickIdx', type, idx);
        }
    }

    _delay_in_win_panel: Subscription = null;
    checkWin() {
        if (!gm.isWin.value && !gm.isLose.value) {
            if (false) {
                this.determineWin();
            }

        }
    }

    determineWin() {
        gm.isWin.value = true;
        let stageInfo = deepclone(this.stageInfo);
        udm.gameWin(stageInfo);
        this._delay_in_win_panel = Timer(.1, this.node).subscribe(_ => {
            let callback = _ => {
                if (_ == 'retry') {
                    this.gamePanel.loadStage();
                } else if (_ == 'exit') {
                    lm.flowStatus.value = FlowStatus.Lobby;
                } else if (_ == 'next') {
                    if (udm.stageNum.value > DevConfig.DIRECT_START_LESSEQUAL_STAGE_NUM) {
                        lm.flowStatus.value = FlowStatus.Lobby;
                    } else {
                        gm.loadNextGameCommand.execute();
                    }
                } else if (_ == 'edit') {
                    lm.flowStatus.value = FlowStatus.EditorGame; // 返回编辑模式
                }
            };

            if (gm.editEnabled.value) {
                EditorGameWinPanel.StartProcess((panel: EditorGameWinPanel) => {
                    panel.stageInfo.value = stageInfo;
                }).subscribe(callback);
            } else {
                GameWinPanel.StartProcess((panel: GameWinPanel) => {
                    panel.stageInfo.value = stageInfo;
                }).subscribe(callback);
            }
        });
    }

    _delay_in_lose_panel: Subscription = null;
    checkLose() {
        if (!gm.isWin.value && !gm.isLose.value) {
            if (false) { // TODO:
                this.determineLose();
            }
        }
    }

    determineLose() {
        if (!gm.isLose.value) {
            gm.isLose.value = true;
            udm.gameLosePopup(this.stageInfo, 'nomoves');
            this._delay_in_lose_panel = Timer(1.5, this.node).subscribe(_ => {
                let callback = _ => {
                    if (_ == 'revive') {
                        gm.isLose.value = false;
                        gm.continueCount.value++;
                        // TODO: 复活相关操作

                    } else if (_ == 'retry') {
                        this.gamePanel.loadStage();
                    } else if (_ == 'exit') {
                        lm.flowStatus.value = FlowStatus.Lobby;
                    } else if (_ == 'edit') {
                        lm.flowStatus.value = FlowStatus.EditorGame; // 返回编辑模式
                    }
                };

                if (gm.editEnabled.value) {
                    EditorGameLosePanel.StartProcess((panel: EditorGameLosePanel) => {
                        panel.stageView = this;
                    }).subscribe(callback.bind(this));
                } else {
                    GameLosePanel.StartProcess((panel: GameLosePanel) => {
                        panel.stageView = this;
                    }).subscribe(callback.bind(this));
                }
            });
        }
    }

    getThinkingTarget() {
        return undefined;
    }
    getThinkingTargetProcess() {
        return undefined;
    }
    getThinkingTargetRate() {
        return undefined;
    }
    getThinkingTargetBlockTypeCount() {
        return undefined;
    }
}

